package base

import (
	"encoding/xml"
	"errors"
	"io/ioutil"
	glog "log"
	"os"
	"path/filepath"

	"github.com/go-redis/redis"
	"github.com/sirupsen/logrus"

	"github.com/jinzhu/gorm"

	//使用mssql数据库
	_ "github.com/jinzhu/gorm/dialects/mssql"
)

//RunMode 运行方式
type RunMode string

const (
	//HTTP HTTP运行方式
	HTTP RunMode = "http"
	//HTTPS HTTPS运行方式
	HTTPS RunMode = "https"
	//FCGI FCGI运行方式
	FCGI RunMode = "fcgi"
)

//WebContext Web上下文
type WebContext struct {
	XMLName       xml.Name `xml:"Web"`
	AppName       string
	RunMode       RunMode
	UI            UI
	Server        Server
	Database      Database
	DatabaseSJ    Database
	RedisSettings []Redis       `xml:"Redis"`
	DataPackages  []DataPackage `xml:"DataPackage"`
	SSRS          SSRS
	Xmla          Xmla
	DataPKG       DataProcessPKG `xml:"DataProcessPKG"`
	Logrun        Logrun
}

//UI UI参数
type UI struct {
	ReportPageNum int `xml:"reportPageNum,attr"`
	BrowsePageNum int `xml:"browsePageNum,attr"`
}

//Server web服务器参数
type Server struct {
	//HTTPPort http端口号
	HTTPPort string `xml:"httpPort,attr"`
	//StaticRootPath 静态内容的根路径
	StaticRootPath string `xml:"staticRootPath,attr"`
	//LandingPage 首页
	LandingPage string `xml:"landingPage,attr"`
}

//Database 数据库的连接配置
type Database struct {
	DbType     string `xml:"dbType,attr"`
	Name       string `xml:"name,attr"`
	ConnString string
	LogMode    bool `xml:"logMode,attr"`
}

//DataPackages 数据包配置列表
type DataPackages struct {
	DataPackages []DataPackage `xml:"DataPackage"`
}

//DataPackage 数据包配置
type DataPackage struct {
	Name        string `xml:"name,attr"`
	Caption     string `xml:"caption,attr"`
	Path        string `xml:"path,attr"`
	Description string `xml:"description,attr"`
}

//Redis 连接参数
type Redis struct {
	//Server 服务器地址
	Server string `xml:"server,attr"`
	//Port 端口号
	Port string `xml:"port,attr"`
	//Password 密码
	Password string `xml:"password,attr"`
}

//SSRS ssrs连接参数
type SSRS struct {
	//UserName 用户名
	UserName string `xml:"userName,attr"`
	//Password 密码
	Password string `xml:"password,attr"`
	//Domain 域
	Domain string `xml:"domain,attr"`
	//Workstation 域
	Workstation string `xml:"workstation,attr"`
	//URL 访问路径D
	Url string
	//Catalog 报表所在目录
	Catalog string
}

//Xmla Xml配置
type Xmla struct {
	UserName       string `xml:"userName,attr"`
	Password       string `xml:"password,attr"`
	Url            string
	DataSourceInfo string
	Catalog        string
	CubeName       string
}

//Logrun Logrun配置
type Logrun struct {
	MaxAge       int64 `xml:"maxAge,attr"`
	RotationTime int64 `xml:"rotationTime,attr"`
}

type DataProcessPKG struct {
	Path string `xml:"path,attr"`
}

//ExecPath 获取程序运行路径
func ExecPath() (string, error) {
	// file, err := os.Getwd()
	// p, err := filepath.Abs(file)
	// if err != nil {
	// 	return "", err
	// }

	executable, err := os.Executable()
	if err != nil {
		return "", err
	}
	symlinks, err := filepath.EvalSymlinks(executable)
	if err != nil {
		return "", err
	}
	rootPath := filepath.Dir(symlinks)

	if rootPath == "." {
		return "", errors.New("dir is empty")
	}
	return rootPath, nil
}

// WorkDir 获取绝对工作路径
func WorkDir() (string, error) {
	// wd := os.Getenv("SHQ_PAS_WORK_DIR")
	// if len(wd) > 0 {
	// 	return wd, nil
	// }
	execPath, err := ExecPath()
	if err != nil {
		return execPath, err
	}
	return execPath, nil
}

//DB 数据库访问对象
var DB *gorm.DB

//ConnectDB 连接数据库
func ConnectDB() (db *gorm.DB, err error) {
	if db, err = gorm.Open(Context.Database.DbType, Context.Database.ConnString); err != nil {
		return nil, err
	}
	db.LogMode(Context.Database.LogMode)
	logger := Logger{logrus.StandardLogger()}
	db.SetLogger(gorm.Logger{LogWriter: logger})
	db.DB().Ping()
	db.DB().SetMaxIdleConns(10)
	db.DB().SetMaxOpenConns(20)
	return db, nil
}

// RedisClient Redis连接客户端0
var RedisClient *redis.Client

// RedisClients Redis连接客户端列表
var RedisClients []*redis.Client

func connRedis(index int) *redis.Client {
	rs := Context.RedisSettings[index]
	addr := rs.Server + ":" + rs.Port
	client := redis.NewClient(&redis.Options{
		Addr:     addr,
		Password: rs.Password,
		DB:       0,
	})
	_, err := client.Ping().Result()
	if err != nil {
		logrus.Panicf("连接redis失败！地址:%s", addr)
		return nil
	}
	logrus.Print("redis.Client就绪！")
	return client
}

//Context web上下文对象
var Context WebContext

func init() {
	var err error
	var workPath string
	if workPath, err = WorkDir(); err != nil {
		logrus.Panicf("获取执行路径出错！%s", err)
		return
	}
	filePath := workPath + "/config/web.xml"
	if xmlBytes, err := ioutil.ReadFile(filePath); err == nil {
		if err := xml.Unmarshal(xmlBytes, &Context); err != nil {
			logrus.Panicf("加载web配置文件失败！%s", err)
		}
	}
	err = ConfigLocalFilesystemLogger()
	if err != nil {
		logrus.Panicf("配置logrun失败%s", err)
	}
	logrus.Info("工作路径：", workPath)
	db, err := ConnectDB()
	if db == nil {
		logrus.Panicf("主数据库连接失败！%s", err)
	} else {
		DB = db
	}
	rsLen := len(Context.RedisSettings)
	RedisClients = make([]*redis.Client, rsLen, rsLen)
	for i := 0; i < rsLen; i++ {
		RedisClients[i] = connRedis(i)
	}
	RedisClient = RedisClients[0]
	err = cacheOrganAndUser()
	if err != nil {
		glog.Panicf("缓存部门员工失败%s", err)
	}
}
func cacheOrganAndUser() (err error) {
	err = GetDepartmentCache().Build()
	if err != nil {
		return
	}
	err = GetEmployeeCache().Build()
	return
}
